/***************************************************************************
 *            make_step.c
 *
 *  Tue Jun 16 21:42:51 2009
 *  Copyright  2009  fantasy
 *  <fantasy614@gmail.com>
 ****************************************************************************/

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
 */

#include <stdlib.h>
#include <stdio.h>
#include "think.h"
#include "global.h"
#include "make_step.h"


void
make_all_steps (int depth, struct step  *parent)
{
		int i,j;
		//int count=0;

		if(depth==0)
			{
					;
			}
		p=steps->firstchild;
        //printf("\nengine:make_all_steps ()\n");
		for(i=0;i<16;i++)
			if (black_side[i ] .loc!=-1)
			{
					j=black_side[i].index;
					//printf("\nengine step src         %d\n\n\n",j);
					switch (j)
						{
								case R_Horse:
										make_horse_step( black_side[i ] .loc);
										break;

								case R_General:
										make_general_step( black_side[i ] .loc);
										break;

								case R_Soldier:
										make_soldier_step( black_side[i ] .loc );
										break;

								case R_Cannon:
										make_cannon_step( black_side[i ] .loc );
										break;

								case R_Advisor:
										make_advisor_step (black_side[i ] .loc);
										break;

								case R_Chariot:
										make_chariot_step ( black_side[i ] .loc);
										break;

								case R_Elephant:
										make_elephant_step (black_side[i ] .loc);
										break;
						}
			}
};


bool is_over_river(int src,int des)
{
			if(chessman_state[src]>10&&des<128)
				return true;
			if(chessman_state[src]<10&& des>128)
				return true;
			return false;


}



void make_horse_step(int src)
{

		int des;
		int i;
		//printf("engine:make_horse_step ()\n");
		for (i = 0; i < 8; i++)
			{
					des=src;
					des+=Horse_step[i][0] ;
					if (is_same_side (src,des)||chessman_state[src-Horse_step[i][1]]>0||chessman_state[des]==-1)
							continue;
					else
						{
								p->nextsibling= (struct step *) malloc (sizeof (struct step ));
								add_step( src, des)	;
								p=p->nextsibling;
						};

			}
		//printf("\np->src  %d\n",p->src);
}
void make_elephant_step(int src)
{

		int des;
		int i;
//		printf("engine:make_elephant_step ()\n");
		for (i = 0; i < 4; i++)
			{
					des=src;
					des+=Elephant_step[i] ;
					if (is_same_side (src,des)|| chessman_state[(des+src)/2]>0||chessman_state[des]==-1 ||!is_over_river(src,(des+src)/2))
							continue;
					else
						{
								p->nextsibling= (struct step *) malloc (sizeof (struct step ));
								add_step( src,des);
								p=p->nextsibling;
						};

			}
//		printf("\np->src  %d\n",p->src);
}


void make_advisor_step(int src)
{

		int des;
		int i;
//		printf("engine:make_advisor_step ()\n");
		for (i = 0; i < 4; i++)
			{
					des=src;
					des+=Advisor_step[i][0] ;
					if (is_same_side (src,des)||infort[des]!=2)
							continue;
					else
						{
								p->nextsibling= (struct step *) malloc (sizeof (struct step ));
								add_step( src,des);
								p=p->nextsibling;
						};
			}
}
void make_soldier_step(int src)
{

		int des;
		int i;
//		printf("engine:make_soldier_step ()\n");
		if(src<128)
			{
					des=src+16;
					if(is_same_side (src,des)||chessman_state[des]==-1)
							return ;
					p->nextsibling= (struct step *) malloc (sizeof (struct step));
					add_step( src,des);
					p=p->nextsibling;
			}
		else
		for (i = 0; i < 3; i++)
			{
					des=src;
					des+=R_Soldier_step[i] ;
					if (is_same_side (src,des)||chessman_state[des]==-1)
							continue;
					else
						{
								p->nextsibling= (struct step *) malloc (sizeof (struct step ));
								add_step( src,des);
								p=p->nextsibling;
						};
			}

}
void make_general_step(int src)
{
		int des;
		int i;
//		printf("engine:make_general_step ()\n");
		for (i = 0; i < 4; i++)
			{
					des=src;
					des+=General_step[i] ;
					if (is_same_side(src,des)||(infort[des]!=2&&infort[des]!=3))
							continue;
					else
						{
								p->nextsibling= (struct step *) malloc (sizeof (struct step ));
								add_step( src,des);
								p=p->nextsibling;
						};
			}
}
void make_cannon_step(int src)
{
	//	int x=src%16,y=src/16;
		int des;
		int flag_1=0,flag_2=0,flag_3=0,flag_4=0;
//		printf("engine:make_cannon_step ()\n");
		for(des=src+1;chessman_state[des]>=0;des++)
			{
					if(chessman_state[des]==0)
						{
								if(flag_1==1)
										continue;
								p->nextsibling= (struct step *) malloc (sizeof (struct step));
								add_step( src,des);
								p=p->nextsibling;
								continue;
						}
					if(chessman_state[des]>0)
						{
								if(flag_1==0)
									{
											flag_1=1;
											continue;
									}
								else
									{
												if(is_same_side(src,des))
													break;
											p->nextsibling= (struct step *) malloc (sizeof (struct step ));
											add_step( src,des);
											p=p->nextsibling;
											break;
									}
						}

			}

		for(des=src-1;chessman_state[des]>=0;des--)
			{
					if(chessman_state[des]==0)
						{
								if(flag_2==1)
										continue;
								p->nextsibling= (struct step *) malloc (sizeof (struct step));
								add_step( src,des);
								p=p->nextsibling;
								continue;
						}
					if(chessman_state[des]>0)
						{
								if(flag_2==0)
									{
											flag_2=1;
											continue;
									}
								else
									{
											if(is_same_side(src,des))
													break;
											p->nextsibling= (struct step *) malloc (sizeof (struct step));
											add_step( src,des);
											p=p->nextsibling;
											break;
									}
						}
			}

		for(des=src-16;chessman_state[des]>=0;des-=16)
			{
					if(chessman_state[des]==0)
						{
								if(flag_3==1)
										continue;
								p->nextsibling= (struct step *) malloc (sizeof (struct step));
								add_step( src,des);
								p=p->nextsibling;
								continue;
						}
					if(chessman_state[des]>0)
						{
								if(flag_3==0)
									{
											flag_3=1;
											continue;
									}
								else
									{
											if(is_same_side(src,des))
													break;
											p->nextsibling= (struct step *) malloc (sizeof (struct step));
											add_step( src,des);
											p=p->nextsibling;
											break;
									}
						}
			}
		for(des=src+16;chessman_state[des]>=0;des+=16)
			{
					if(chessman_state[des]==0)
						{
									if(flag_4==1)
										continue;
								p->nextsibling= (struct step *) malloc (sizeof (struct step));
								add_step( src,des);
								p=p->nextsibling;
								continue;
						}
					if(chessman_state[des]>0)
						{
								if(flag_4==0)
									{
											flag_4=1;
											continue;
									}
								else
									{
											if(is_same_side(src,des))
													break;
											p->nextsibling= (struct step *) malloc (sizeof (struct step ));
											add_step( src,des);
											p=p->nextsibling;
											break;
									}
						}
			}

}
;
void make_chariot_step(int src)
{
		//int x=src%16,y=src/16;
		int des;
		//	int flag=0;
//		printf("engine:make_chariot_step ()\n");

		for(des=src+1;chessman_state[des]>=0;des++)
			{
					if(chessman_state[des]==0)
						{
								p->nextsibling= (struct step *) malloc (sizeof (struct step ));
								add_step( src,des);
								p=p->nextsibling;
								continue;
						}
					if(is_same_side (src,des))
							break;

					p->nextsibling= (struct step *) malloc (sizeof (struct step ));
					add_step( src,des);
					p=p->nextsibling;
					break;


			}

		for(des=src-1;chessman_state[des]>=0;des--)
			{
					if(chessman_state[des]==0)
						{
								p->nextsibling= (struct step *) malloc (sizeof (struct step));
								add_step( src,des);
								p=p->nextsibling;
								continue;
						}
					if(chessman_state[des]>0)
						{
								if(is_same_side (src,des))
										break;
								p->nextsibling= (struct step *) malloc (sizeof (struct step));
								add_step( src,des);
								p=p->nextsibling;
								break;
						}

			}
		for(des=src+16;chessman_state[des]>=0;des+=16)
			{
					if(chessman_state[des]==0)
						{
								p->nextsibling= (struct step *) malloc (sizeof (struct step));
								add_step( src,des);
								p=p->nextsibling;
								continue;
						}

					if(chessman_state[des]>0)
						{
								if(is_same_side (src,des))
										break;
								p->nextsibling= (struct step *) malloc (sizeof (struct step));
								add_step( src,des);
								p=p->nextsibling;
								break;
						}



			}
		for(des=src-16;chessman_state[des]>=0;des-=16)
			{

					if(chessman_state[des]==0)
						{
								p->nextsibling= (struct step *) malloc (sizeof (struct step ));
								add_step( src,des);
								p=p->nextsibling;
								continue;
						}
					if(chessman_state[des]>0)
						{
								if(is_same_side (src,des))
										break;
								p->nextsibling= (struct step *) malloc (sizeof (struct step ));
								add_step( src,des);
								p=p->nextsibling;
								break;
						}

			}


};



//添加一步棋
void add_step(int src,int des)
{
		struct step *new_step;
		int i;
		struct piece *src_side,*des_side;
//		printf("engine:add_step ()\n");
		new_step = (struct step *) malloc (sizeof (struct step));

		new_step->src=src;
		new_step->des=des;
		for(i=0;i<16;i++)
			{
				//	g_print("black_side[%d].index %d   black_side[%d].loc   %d \n",i,black_side[i].index,i,black_side[i].loc);

					new_step->black_side[i].loc=black_side[i].loc;
					new_step->black_side[i].index=black_side[i].index;

				//	g_print("red_side[%d].index %d   red_side[%d].loc   %d \n",i,red_side[i].index,i,red_side[i].loc);

					new_step->red_side[i].loc=red_side[i].loc;
					new_step->red_side[i].index=red_side[i].index;
					//g_print("hello");
			}
		//判断是哪边

		src_side=(struct piece *)malloc(sizeof(struct piece));
		des_side=(struct piece *)malloc(sizeof(struct piece ));
		src_side=(chessman_state[src]>10)?new_step->black_side: new_step->red_side;
		des_side=(chessman_state[src]>10)?new_step->red_side:	new_step->black_side;
		for(i=0;i<16;i++)
			{
					if(des_side->loc==des)
						{
							des_side->loc=-1;
								break;
						}
						else
							des_side++;
			}
		for(i=0;i<16;i++)
			{
					if(src_side->loc==src)
						{
							src_side->loc=des;
							break;
						}
					else
							src_side++;
			}
//		printf("add_step: src %d   des %d\n",src,des);
		new_step->score=get_vaule(new_step);
		p->nextsibling=new_step;
}
